Skip to content

Export resolveI18nLabel and fix i18n label type errors in plugin-designer#901

Merged
hotlong merged 2 commits intomainfrom
copilot/fix-type-assignments-errors
Feb 28, 2026
Merged

Export resolveI18nLabel and fix i18n label type errors in plugin-designer#901
hotlong merged 2 commits intomainfrom
copilot/fix-type-assignments-errors

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 28, 2026

NavigationItem.label is typed as string | { key; defaultValue?; params? } but several files treat it as a plain string, causing TS2322/TS2339 build failures across plugin-designer and components.

  • packages/react/src/index.ts — Export resolveI18nLabel from ./utils/i18n. It was defined but not re-exported, breaking imports in breadcrumb.tsx and header-bar.tsx.
  • packages/plugin-designer/src/NavigationDesigner.tsx — Resolve i18n labels to strings at all 5 usage sites (state init, commit handler, escape reset, display render, preview render).
  • packages/plugin-designer/src/AppCreationWizard.tsx — Wrap item.label with resolveI18nLabel() in nav preview list.
// Before — TS error: i18n object not assignable to ReactNode
<span>{item.label}</span>

// After
<span>{resolveI18nLabel(item.label)}</span>
Original prompt

09:55:37.275 @object-ui/plugin-designer:build: �[96msrc/AppCreationWizard.tsx�[0m:�[93m527�[0m:�[93m17�[0m - �[91merror�[0m�[90m TS2322: �[0mType 'string | { key: string; defaultValue?: string | undefined; params?: Record<string, any> | undefined; }' is not assignable to type 'ReactNode'.
09:55:37.275 @object-ui/plugin-designer:build: Type '{ key: string; defaultValue?: string | undefined; params?: Record<string, any> | undefined; }' is not assignable to type 'ReactNode'.
09:55:37.276 @object-ui/plugin-designer:build: Type '{ key: string; defaultValue?: string | undefined; params?: Record<string, any> | undefined; }' is missing the following properties from type 'ReactPortal': children, type, props
09:55:37.276 @object-ui/plugin-designer:build: �[96msrc/NavigationDesigner.tsx�[0m:�[93m151�[0m:�[93m20�[0m - �[91merror�[0m�[90m TS2339: �[0mProperty 'trim' does not exist on type 'string | { key: string; defaultValue?: string | undefined; params?: Record<string, any> | undefined; }'.
09:55:37.276 @object-ui/plugin-designer:build: Property 'trim' does not exist on type '{ key: string; defaultValue?: string | undefined; params?: Record<string, any> | undefined; }'.
09:55:37.276 @object-ui/plugin-designer:build: �[96msrc/NavigationDesigner.tsx�[0m:�[93m152�[0m:�[93m41�[0m - �[91merror�[0m�[90m TS2339: �[0mProperty 'trim' does not exist on type 'string | { key: string; defaultValue?: string | undefined; params?: Record<string, any> | undefined; }'.
09:55:37.276 @object-ui/plugin-designer:build: Property 'trim' does not exist on type '{ key: string; defaultValue?: string | undefined; params?: Record<string, any> | undefined; }'.
09:55:37.277 @object-ui/plugin-designer:build: �[96msrc/NavigationDesigner.tsx�[0m:�[93m240�[0m:�[93m13�[0m - �[91merror�[0m�[90m TS2322: �[0mType 'string | { key: string; defaultValue?: string | undefined; params?: Record<string, any> | undefined; }' is not assignable to type 'string | number | readonly string[] | undefined'.
09:55:37.277 @object-ui/plugin-designer:build: Type '{ key: string; defaultValue?: string | undefined; params?: Record<string, any> | undefined; }' is not assignable to type 'string | number | readonly string[] | undefined'.
09:55:37.277 @object-ui/plugin-designer:build: �[96msrc/NavigationDesigner.tsx�[0m:�[93m266�[0m:�[93m13�[0m - �[91merror�[0m�[90m TS2322: �[0mType 'string | { key: string; defaultValue?: string | undefined; params?: Record<string, any> | undefined; }' is not assignable to type 'ReactNode'.
09:55:37.278 @object-ui/plugin-designer:build: Type '{ key: string; defaultValue?: string | undefined; params?: Record<string, any> | undefined; }' is not assignable to type 'ReactNode'.
09:55:37.278 @object-ui/plugin-designer:build: Type '{ key: string; defaultValue?: string | undefined; params?: Record<string, any> | undefined; }' is missing the following properties from type 'ReactPortal': children, type, props
09:55:37.278 @object-ui/plugin-designer:build: �[96msrc/NavigationDesigner.tsx�[0m:�[93m413�[0m:�[93m36�[0m - �[91merror�[0m�[90m TS2322: �[0mType 'string | { key: string; defaultValue?: string | undefined; params?: Record<string, any> | undefined; }' is not assignable to type 'ReactNode'.
09:55:37.278 @object-ui/plugin-designer:build: Type '{ key: string; defaultValue?: string | undefined; params?: Record<string, any> | undefined; }' is not assignable to type 'ReactNode'.
09:55:37.278 @object-ui/plugin-designer:build: Type '{ key: string; defaultValue?: string | undefined; params?: Record<string, any> | undefined; }' is missing the following properties from type 'ReactPortal': children, type, props
09:55:59.698 @object-ui/components:build: �[96msrc/renderers/data-display/breadcrumb.tsx�[0m:�[93m13�[0m:�[93m10�[0m - �[91merror�[0m�[90m TS2305: �[0mModule '"@object-ui/react"' has no exported member 'resolveI18nLabel'.
09:55:59.698 @object-ui/components:build: �[96msrc/renderers/navigation/header-bar.tsx�[0m:�[93m12�[0m:�[93m10�[0m - �[91merror�[0m�[90m TS2305: �[0mModule '"@object-ui/react"' has no exported member 'resolveI18nLabel'.
09:56:42.560 @object-ui/plugin-list:build: �[31merror during build:
09:56:42.567 @object-ui/plugin-list:build: at error (file:///vercel/path0/node_modules/.pnpm/rollup@4.57.1/node_modules/rollup/dist/es/shared/parseAst.js:398:42)
09:56:42.667 @object-ui/plugin-list:build:  ELIFECYCLE  Command failed with exit code 1.
09:56:42.680 @object-ui/plugin-list:build: ERROR: command finished with error: command (/vercel/path0/packages/plugin-list) /vercel/.local/share/pnpm/.tools/pnpm/10.28.2/bin/pnpm run build exited (1)
09:56:42.740 @object-ui/fields:build:  ELIFECYCLE  Command failed.
09:56:42.746 @object-ui/plugin-list#build: command (/vercel/path0/packages/plugin-list) /vercel/.local/share/pnpm/.tools/pnpm/10.28.2/bin/pnpm run build exited (1)
09:56:42.763 ERROR run failed: command exited (1)
09:56:42.782 Error: Command "cd ../.. && pnpm turbo run build --filter=@object-ui/console^... && cd apps...


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
objectui Ready Ready Preview, Comment Feb 28, 2026 2:26am
objectui-demo Ready Ready Preview, Comment Feb 28, 2026 2:26am
objectui-storybook Ready Ready Preview, Comment Feb 28, 2026 2:26am

Request Review

…n label handling in plugin-designer

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix type assignment errors in AppCreationWizard and NavigationDesigner Export resolveI18nLabel and fix i18n label type errors in plugin-designer Feb 28, 2026
@hotlong hotlong marked this pull request as ready for review February 28, 2026 04:19
Copilot AI review requested due to automatic review settings February 28, 2026 04:19
@hotlong hotlong merged commit eca8efc into main Feb 28, 2026
5 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes TypeScript build failures caused by treating NavigationItem.label (string | i18n object) as a plain string across plugin-designer and components, by standardizing label rendering through resolveI18nLabel exported from @object-ui/react.

Changes:

  • Re-export resolveI18nLabel from @object-ui/react to unblock downstream imports.
  • Update NavigationDesigner to resolve labels to strings at all UI/editing usage sites.
  • Update AppCreationWizard navigation preview to render labels via resolveI18nLabel.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
packages/react/src/index.ts Re-exports resolveI18nLabel to make label resolution available to other packages.
packages/plugin-designer/src/NavigationDesigner.tsx Uses resolveI18nLabel for label draft state + rendering to avoid union-type misuse.
packages/plugin-designer/src/AppCreationWizard.tsx Resolves navigation preview labels via resolveI18nLabel to fix ReactNode typing errors.

Comment on lines +17 to +18
export { resolveI18nLabel } from './utils/i18n';

Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolveI18nLabel is now part of the public @object-ui/react API, but its current fallback uses label.defaultValue || label.key, which will ignore an intentionally empty-string defaultValue and show the key instead. Consider switching the implementation to nullish coalescing (defaultValue ?? key) so empty strings are preserved while still falling back when defaultValue is truly missing.

Suggested change
export { resolveI18nLabel } from './utils/i18n';
import { resolveI18nLabel as baseResolveI18nLabel } from './utils/i18n';
export function resolveI18nLabel(
...args: Parameters<typeof baseResolveI18nLabel>
): ReturnType<typeof baseResolveI18nLabel> {
const [label] = args;
if (
label &&
typeof label === 'object' &&
'defaultValue' in label &&
(label as { defaultValue?: unknown }).defaultValue === ''
) {
// Preserve intentionally empty-string default values instead of falling back to the key
return '' as ReturnType<typeof baseResolveI18nLabel>;
}
return baseResolveI18nLabel(...args);
}

Copilot uses AI. Check for mistakes.
Comment on lines 142 to 144
const [editingLabel, setEditingLabel] = useState(false);
const [labelDraft, setLabelDraft] = useState(item.label);
const [labelDraft, setLabelDraft] = useState(resolveI18nLabel(item.label) ?? '');
const [editingIcon, setEditingIcon] = useState(false);
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test coverage: the new label resolution path should be exercised with a NavigationItem.label i18n object (e.g. { key, defaultValue }) to ensure the designer renders/edits without runtime errors and shows the expected fallback string. Adding a focused test case in NavigationDesigner.test.tsx would prevent regressions for this union type.

Copilot uses AI. Check for mistakes.
Comment on lines 527 to 529
<span className="flex-1 truncate text-sm text-gray-800">
{item.type === 'separator' ? t('appDesigner.separatorLabel') : item.label}
{item.type === 'separator' ? t('appDesigner.separatorLabel') : resolveI18nLabel(item.label)}
</span>
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test coverage: since the navigation preview now resolves item.label via resolveI18nLabel, add a test case in AppCreationWizard.test.tsx with an i18n-object label to ensure the preview renders the expected fallback string (and doesn’t regress back to TS/ReactNode issues).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants